home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / infop125.arc / INFOPLUS.ASM next >
Assembly Source File  |  1991-04-28  |  15KB  |  586 lines

  1. ;--------------------------------------------------------------------
  2. ;
  3. ;       INFOPLUS.ASM
  4. ;
  5. ;       Version 1.25
  6. ;
  7. ;       Four subprograms used by INFOPLUS.PAS:
  8. ;
  9. ;               CPUID           - identifies host CPU and NDP (if
  10. ;                                       any)
  11. ;               DISKREAD        - reads absolute sectors from disk
  12. ;               LONGCALL        - calls a routine using a CALL FAR
  13. ;        ATIINFO        - for accessing ATI VGAWonder cards
  14. ;
  15. ;       Originally by:
  16. ;       Steve Grant
  17. ;       Long Beach, CA
  18. ;       January 13, 1989
  19. ;
  20. ;       mods by Andrew Rossmann (8/10/90)
  21. ;--------------------------------------------------------------------
  22.  
  23. .286P
  24. .8087
  25.  
  26.         public  CPUID, DISKREAD, LONGCALL, ATIINFO
  27.  
  28. CODE    segment byte
  29.  
  30. ;       Conditional jumps are all coded with the SHORT qualifier in
  31. ;       order to minimize the size of the .OBJ file output of Turbo
  32. ;       Assembler.
  33.  
  34. ;--------------------------------------------------------------------
  35.  
  36. CPUID   proc    near
  37.  
  38. assume  cs:CODE, ds:DATA, es:nothing, ss:nothing
  39.  
  40. ;       On entry:
  41. ;
  42. ;               BP
  43. ;       SP =>   near return address
  44. ;               offset  of a cpu_info_t record
  45. ;               segment "  "     "        "
  46. ;    also, the test type byte should be a 'C' or 'N' to execute the
  47. ;    CPU or NDP tests.
  48. ;
  49. ;       On exit, the cpu_info_t record has been filled in as follows:
  50. ;
  51. ;               byte    = CPU type
  52. ;               word    = Machine Status Word
  53. ;               6 bytes = Global Descriptor Table
  54. ;               6 bytes = Interrupt Descriptor Table
  55. ;               boolean = segment register change/interrupt flag
  56. ;               byte    = NDP type
  57. ;               word    = NDP control word
  58. ;        byte    = test type (C or N)
  59.  
  60. mCPU    equ     byte ptr [bx]
  61. mMSW    equ     word ptr [bx + 1]
  62. mGDT    equ     [bx + 3]
  63. mIDT    equ     [bx + 9]
  64. mchkint equ     byte ptr [bx + 15]
  65. mNDP    equ     byte ptr [bx + 16]
  66. mNDPCW  equ     word ptr [bx + 17]
  67. mtest    equ    byte ptr [bx + 19]
  68.  
  69. f8088   equ     0
  70. f8086   equ     1
  71. fV20    equ     2
  72. fV30    equ     3
  73. f80188  equ     4
  74. f80186  equ     5
  75. f80286  equ     6
  76. f80386  equ     7
  77. f80486  equ     8
  78. funk    =       0FFH
  79.  
  80. false   equ     0
  81. true    equ     1
  82.  
  83.         push    bp
  84.         mov     bp,sp
  85.         push    ds
  86.         lds     bx,[bp + 4]
  87.     cmp    mtest, 'C'
  88.     jnz    skipcpu
  89.         call    cpu
  90.         call    chkint
  91. skipcpu:
  92.     cmp    mtest, 'N'
  93.     jnz    skipndp
  94.         call    ndp
  95. skipndp:
  96.         pop     ds
  97.         pop     bp
  98.         ret     4
  99.  
  100. ;--------------------------------------------------------------------
  101.  
  102. cpu:
  103.  
  104. ; interrupt of multi-prefix string instruction
  105.  
  106.         mov     mCPU,funk               ;set CPU type to unknown
  107.         sti
  108.         mov     cx,0FFFFH
  109. rep     lods    byte ptr es:[si]
  110.         jcxz    short cpu_02
  111.         call    piq
  112.         cmp     dx,4
  113.         jg      short cpu_01
  114.         mov     mCPU,f8088
  115.         ret
  116. cpu_01:
  117.         cmp     dx,6
  118.         jne     short cpu_01a
  119.         mov     mCPU,f8086
  120. cpu_01a:
  121.         ret
  122. cpu_02:
  123.  
  124. ; number of bits in displacement register used by shift
  125.  
  126.         mov     al,0FFH
  127.         mov     cl,20H
  128.         shl     al,cl
  129.         or      al,al
  130.         jnz     short cpu_04
  131.         call    piq
  132.         cmp     dx,4
  133.         jg      short cpu_03
  134.         mov     mCPU,fV20
  135.         ret
  136. cpu_03:
  137.         cmp     dx,6
  138.         je      cpu_03a
  139.         jmp     CPUID_done
  140. cpu_03a:
  141.         mov     mCPU,fV30
  142.         ret
  143. cpu_04:
  144.  
  145. ; order of write/decrement by PUSH SP
  146.  
  147.         push    sp
  148.         pop     ax
  149.         cmp     ax,sp
  150.         je      short cpu_06
  151.         call    piq
  152.         cmp     dx,4
  153.         jg      short cpu_05
  154.         mov     mCPU,f80188
  155.         ret
  156. cpu_05:
  157.         cmp     dx,6
  158.         jne     short CPUID_done
  159.         mov     mCPU,f80186
  160.         ret
  161.  
  162. ;First, grab some tables
  163.  
  164. cpu_06:
  165.         smsw    mMSW
  166.         sgdt    mGDT
  167.         sidt    mIDT
  168.  
  169. ;!!!!!!!
  170. ;!!! Original 286/386 detection code (modified 8/10/90)
  171. ;!!! Modified by code supplied by John Levine, apparantly from an Intel
  172. ;!!! '486 manual.
  173. ;!!!!!!!
  174.  
  175.         pushf                ;put flags into CX
  176.     pop    cx
  177.     and    cx,0fffh        ;mask off upper 4 bits
  178.     push    cx
  179.     popf
  180.     pushf
  181.     pop    ax
  182.     and    ax,0f000h        ;look only at upper 4 bits
  183.     cmp    ax,0f000h        ;88/86 etc.. turn them on
  184.     jz    badcpu            ;not 286/386/486!!!
  185.     or    cx,0f000h        ;force upper 4 bits on
  186.     push    cx
  187.     popf
  188.     pushf
  189.     pop    ax
  190.     and    ax,0f000h
  191.     jz    found286        ;bits are zeroed in real mode 286
  192. .386
  193.     mov    dx,sp            ;save current stack position
  194.     and    sp,not 3        ;dword align to avoid traps
  195.     pushfd                ;push 32 bit flag
  196.     pop    eax
  197.     mov    ecx,eax
  198.     xor    eax,40000h        ;flip AC (alignment check) flag
  199.     push    eax
  200.     popfd
  201.     pushfd
  202.     pop    eax
  203.     mov    sp,dx
  204.     xor    eax,ecx            ;was bit changed??
  205.     test    eax,40000h
  206. .286
  207.     jz    found386        ;if not, is a 386
  208.     mov    mCPU,f80486        ;must be a 486!!
  209.     jmp    short CPUID_done
  210. found286:
  211.         mov     mCPU,f80286
  212.     jmp    short CPUID_done
  213. found386:
  214.         mov     mCPU,f80386
  215.         jmp    short CPUID_done
  216. badcpu:
  217.     mov    mCPU,funk        ;how'd an 8088 get this far?????
  218. CPUID_done:
  219.         ret
  220. ;--------------------------------------------------------------------
  221.  
  222. piq:
  223.  
  224. ;       On exit:
  225. ;
  226. ;               DX      = length of prefetch instruction queue
  227. ;
  228. ;       This subroutine uses self-modifying code, but can
  229. ;       nevertheless be run repeatedly in the course of the calling
  230. ;       program.
  231.  
  232. count   =       7
  233. opincdx equ     42H                     ; inc dx opcode
  234. opnop   equ     90H                     ; nop opcode
  235.  
  236.         mov     al,opincdx
  237.         mov     cx,count
  238.         push    cx
  239.         push    cs
  240.         pop     es
  241.         mov     di,offset piq_01 - 1
  242.         push    di
  243.         std
  244.         rep stosb
  245.         mov     al,opnop
  246.         pop     di
  247.         pop     cx
  248.         xor     dx,dx
  249.         cli
  250.         rep stosb
  251.         rept    count
  252.         inc     dx
  253.         endm
  254. piq_01:
  255.         sti
  256.         ret
  257.  
  258. ;--------------------------------------------------------------------
  259.  
  260. chkint:
  261.  
  262. ; save old INT 01H vector
  263.  
  264.         push    bx
  265.         mov     ax,3501H
  266.         int     21H
  267.         mov     old_int01_ofs,bx
  268.         mov     old_int01_seg,es
  269.         pop     bx
  270.  
  271. ; redirect INT 01H vector
  272.  
  273.         push    ds
  274.         mov     ax,2501H
  275.         mov     dx,seg new_int01
  276.         mov     ds,dx
  277.         mov     dx,offset new_int01
  278.         int     21H
  279.         pop     ds
  280.  
  281. ; set TF and change SS -- did we trap on following instruction?
  282.  
  283.         pushf
  284.         pop     ax
  285.         or      ah,01H                  ; set TF
  286.         push    ax
  287.         popf
  288.         push    ss                      ; CPU may wait one
  289.                                         ; instruction before
  290.                                         ; recognizing single step
  291.                                         ; interrupt
  292.         pop     ss
  293. chkint_01:                              ; shouldn't ever trap here
  294.  
  295. ; restore old INT 01H vector
  296.  
  297.         push    ds
  298.         mov     ax,2501H
  299.         lds     dx,old_int01
  300.         int     21H
  301.         pop     ds
  302.         ret
  303.  
  304. ;--------------------------------------------------------------------
  305.  
  306. new_int01:
  307.  
  308. ;       INT 01H handler (single step)
  309. ;
  310. ;       On entry:
  311. ;
  312. ;       SP =>   IP
  313. ;               CS
  314. ;               flags
  315.  
  316.         sti
  317.         pop     ax                      ; IP
  318.         cmp     ax,offset chkint_01
  319.         jb      short new_int01_03
  320.         je      short new_int01_01
  321.         mov     mchkint,false
  322.         jmp     short new_int01_02
  323. new_int01_01:
  324.         mov     mchkint,true
  325. new_int01_02:
  326.         pop     cx                      ; CS
  327.         pop     dx                      ; flags
  328.         and     dh,0FEH                 ; turn off TF
  329.         push    dx                      ; flags
  330.         push    cx                      ; CS
  331. new_int01_03:
  332.         push    ax                      ; IP
  333.         iret
  334. ;--------------------------------------------------------------------
  335.  
  336. ndp:
  337.  
  338. fnone   equ     0
  339. f8087   equ     1
  340. f80287  equ     2
  341. f80387  equ     3
  342. funk    =       0FFH
  343.  
  344.         mov     word ptr ndp_cw,0000H
  345.         cli
  346.  
  347. ; The next three 80x87 instructions cannot carry the WAIT prefix,
  348. ; because there may not be an 80x87 for which to wait.  The WAIT is
  349. ; therefore emulated with a MOV CX,<value>! LOOP $ combination.
  350.  
  351. .287
  352.                                         ;       CPU     NDP
  353.         fnsave  ndp_save                ;        14     221
  354.         mov     cx,(221-6-1)/17+1       ;         4
  355.         loop    $                       ;  17*CX-12
  356.                                         ;   17*CX+6
  357.  
  358.         fninit                          ;         8       8
  359.         mov     cx,(8-0-1)/17+1         ;         4
  360.         loop    $                       ;  17*CX-12
  361.                                         ;     17*CX
  362.  
  363.         fnstcw  ndp_cw                  ;        14      24
  364.         mov     cx,14h
  365.         loop    $                       ;  17*CX-12
  366.                                         ;   17*CX+2
  367.  
  368.         sti
  369.         mov     ax,ndp_cw
  370.     and    ax,0f3fh
  371.         cmp     ax,33fh
  372.         je      short ndp_01
  373.         mov     mNDP,fnone
  374.         ret
  375. ndp_01:
  376.     mov    ax,ndp_cw
  377.         cmp     ax,03FFH
  378.         jne     short ndp_02
  379.         mov     mNDP,f8087
  380.         jmp     short ndp_04
  381. ndp_02:
  382.  
  383. .287
  384.  
  385.         cmp     ax,037FH
  386.         jne     short ndp_05
  387.         fld1
  388.         fldz
  389.         fdiv
  390.         fld1
  391.         fchs
  392.         fldz
  393.         fdiv
  394.         fcom
  395.         fstsw   ndp_sw
  396.         mov     ax,ndp_sw
  397.         and     ah,41H                  ; C3, C0
  398.         cmp     ah,40H                  ; ST(0) = ST(1)
  399.         jne     short ndp_03
  400.         mov     mNDP,f80287
  401.         jmp     short ndp_04
  402. ndp_03:
  403.         cmp     ah,01H                  ; ST(0) < ST(1)
  404.         jne     short ndp_05
  405.         mov     mNDP,f80387
  406. ndp_04:
  407.  
  408. .8087
  409.  
  410.         frstor  ndp_save
  411.         fstcw   mNDPCW
  412.         ret
  413. ndp_05:
  414.         mov     mNDP,funk
  415.         ret
  416.  
  417. CPUID   endp
  418.  
  419. ;--------------------------------------------------------------------
  420.  
  421. DISKREAD        proc    near
  422.  
  423. assume cs:CODE, ds:DATA, es:nothing
  424.  
  425. ;       On entry:
  426. ;
  427. ;               BP
  428. ;       SP =>   near return address
  429. ;               offset  of disk buffer
  430. ;               segment "   "     "
  431. ;               number of sectors to read
  432. ;               starting logical sector number
  433. ;               drive number (0=A, 1=B, etc.)
  434. ;
  435. ;       On exit:
  436. ;
  437. ;               AX      = function result
  438. ;                       00      - function successful
  439. ;                       01..FF  - DOS INT 25H error result
  440.  
  441.         drive                   equ     [bp + 12]
  442.         starting_sector         equ     [bp + 10]
  443.         number_of_sectors       equ     [bp + 8]
  444.         buffer                  equ     [bp + 4]
  445.  
  446.         push    bp
  447.         mov     bp,sp
  448.         mov     ax,3000h                ;get DOS version
  449.         int     21h
  450.         cmp     al,4                    ;DOS 4?
  451.         jb      read3                   ;Read assuming DOS 3.x
  452.         mov     al,drive
  453.         mov     bx,starting_sector      ;copy info into parameter block
  454.         mov     extd_starting_sector_lo,bx
  455.         mov     extd_starting_sector_hi,0       ;We're only using lower part
  456.         mov     bx,number_of_sectors
  457.         mov     extd_number_of_sectors,bx
  458.         les     bx,buffer               ;get seg:ofs of buffer in ES:BX
  459.         mov     extd_bufofs,bx          ;put into block
  460.         mov     extd_bufseg,es
  461.         mov     bx,offset dos4_block    ;DS:BX points to block
  462.         mov     cx,-1                   ;-1 means extended read
  463.         push    ds                      ;save DS (not really needed, but lets
  464.                                         ;me share code with DOS 3 read.)
  465.         jmp     short readit
  466.  
  467. read3:  mov     al,drive
  468.         mov     dx,starting_sector
  469.         mov     cx,number_of_sectors
  470.         push    ds
  471.         lds     bx,buffer               ;get seg:ofs of buffer in DS:BX
  472. readit: int     25H
  473.         inc     sp                      ; fix broken stack
  474.         inc     sp
  475.         pop     ds
  476.         jc      short diskread_01
  477.         xor     ax,ax
  478. diskread_01:
  479.  
  480.         pop     bp
  481.         ret     10
  482.  
  483. DISKREAD        endp
  484.  
  485. ;
  486. ;LONGCALL will call a routine using a CALL FAR. This is used by XMS
  487. ;
  488. ;Pascal format: procedure longcall(AXi: word; var addr: longint;
  489. ;                                  var AXo, BXo, DXo: word); external;
  490. ;
  491.  
  492. longcall        proc    near
  493.         assume  cs:CODE, ds:DATA, es:nothing
  494.  
  495. AXi     equ     [bp+20]                 ;set up correct pointers
  496. addr    equ     [bp+16]
  497. AXo     equ     [bp+12]
  498. BXo     equ     [bp+8]
  499. DXo     equ     [bp+4]
  500.  
  501.         push    bp                      ;setup BP
  502.         mov     bp,sp
  503.         les     di,addr                 ;copy address to call into
  504.         mov     ax,es:[di]              ; local variable
  505.         mov     word ptr address,ax
  506.         mov     ax,es:[di+2]
  507.         mov     word ptr address+2,ax
  508.         mov     ax,AXi                  ;get function number
  509.         call    dword ptr address       ;do far call
  510.         les     di,DXo                  ;save DX, BX, and AX to correct
  511.         mov     [es:di],dx              ; Pascal variables.
  512.         les     di,BXo
  513.         mov     [es:di],bx
  514.         les     di,AXo
  515.         mov     [es:di],ax
  516.         pop     bp                      ;restore stack
  517.         ret     18
  518. longcall endp
  519.  
  520. ;
  521. ; ATIINFO is used in the Video identification routine to get special
  522. ; information from ATI VGA Wonder cards.
  523. ;
  524. ; Pascal format: function ATIinfo(data_in: byte, register: word): byte;
  525. ;
  526. ATIinfo        proc    near
  527.     assume    cs:CODE, ds:DATA, es:NOTHING
  528.  
  529. data_in        equ    [bp+6]
  530. register    equ    [bp+4]
  531.  
  532.     push    bp
  533.     mov    bp,sp
  534.     mov    dx,register        ;get register
  535.     mov    ax,data_in        ;get command word (actually byte)
  536.     cli                ;no interrupts
  537.     out    dx,al
  538.     inc    dx            ;next port
  539.     in    al,dx            ;get result
  540.     sti                ;restore interrupts
  541.     mov    sp,bp
  542.     pop    bp
  543.     ret    4
  544.  
  545. ATIinfo    endp
  546.  
  547. code    ends
  548.  
  549. ;--------------------------------------------------------------------
  550.  
  551. DATA    segment byte
  552.  
  553. ; storage for CPUID
  554.  
  555. ; redirected INT 01H vector
  556.  
  557. old_int01       label   dword
  558. old_int01_ofs   dw      ?
  559. old_int01_seg   dw      ?
  560.  
  561. ; storage for NDPID
  562.  
  563. ; 80x87 control word after initialization, status word after divide by zero
  564.  
  565. ndp_cw          dw      ?
  566. ndp_save        db      94 dup (?)
  567. ndp_sw          dw      ?
  568.  
  569. ; storage for DISKREAD
  570.  
  571. ; DOS 4.0 extended read parameter block
  572. dos4_block                      label   byte
  573. extd_starting_sector_lo         dw      ?
  574. extd_starting_sector_hi         dw      ?
  575. extd_number_of_sectors          dw      ?
  576. extd_bufofs                     dw      ?
  577. extd_bufseg                     dw      ?
  578.  
  579. ; storage for LONGCALL
  580.  
  581. address dd      ?
  582.  
  583. DATA    ends
  584.  
  585.         end
  586.